import 'dart:convert';
import 'dart:io';

import 'package:flutter/services.dart';
import 'package:flutter_account_book/utils/db/dao/account_record.dart';
import 'package:flutter_account_book/utils/db/dao/record_type.dart';
import 'package:flutter_account_book/utils/db/entities/record_type.dart';
import 'package:get/get.dart';
import 'package:flutter_account_book/utils/db/dao/account_book.dart';
import 'package:flutter_account_book/utils/db/entities/account_book.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart' as path;

import 'dao/pay_method.dart';

class DbHelper extends GetxController {
  static void instance() {
    Get.put(DbHelper());
  }

  static DbHelper get helper => Get.find();

  late Database db;

  @override
  void onInit() {
    super.onInit();
    _initDb();
  }

  _initDb() async {
    Directory documentsDirectory = await getApplicationDocumentsDirectory();
    String p = path.join(documentsDirectory.path, "account.db");
    db = await openDatabase(p,
        version: 1, onUpgrade: _onUpgrade, onCreate: _onCreate);
  }

  void _onCreate(Database db, int version) async {
    print("初始数据库进来了------------");
    if (Platform.isAndroid) {
      db.androidSetLocale('zh-CN');
    }

    await db.execute("CREATE TABLE account_books("
        "id INTEGER PRIMARY KEY,"
        "name TEXT,"
        "`order` INTEGER DEFAULT 0,"
        "asyncService INTEGER DEFAULT 0,"
        "deleted INTEGER DEFAULT 0)");

    await db.insert('account_books', {
      "id": AccountBook.idAll,
      "name": "我的账单",
      "order": -10,
      "asyncService": 1
    });

    await db.execute("CREATE TABLE account_records("
        "id TEXT PRIMARY KEY,"
        "amount REAL NOT NULL,"
        "recordTime INTEGER DEFAULT 0,"
        "createTime INTEGER,"
        "updateTime INTEGER,"
        "payMethod TEXT,"
        "payMethodId INTEGER,"
        "recordType TEXT,"
        "recordTypeId INTEGER,"
        "remark TEXT,"
        "books INTEGER,"
        "asyncService INTEGER DEFAULT 0,"
        "isIncome INTEGER DEFAULT 0,"
        "deleted INTEGER DEFAULT 0)");

    await db.execute("CREATE TABLE pay_methods("
        "id INTEGER PRIMARY KEY AUTOINCREMENT,"
        "name INTEGER,"
        "type INTEGER DEFAULT 0,"
        "iconPath TEXT,"
        "`order` INTEGER DEFAULT 0)");

    await rootBundle
        .loadString("assets/data/initPayTypeDefaultData.json")
        .then((jsonStr) async {
      List jsonList = jsonDecode(jsonStr);
      for (var element in jsonList) {
        await db.insert('pay_methods', element);
      }
    });

    await db.execute("CREATE TABLE record_types("
        "id INTEGER PRIMARY KEY AUTOINCREMENT,"
        "name INTEGER,"
        "type INTEGER DEFAULT 0,"
        "iconPath TEXT,"
        "isIncome INTEGER DEFAULT 0,"
        "backgroundColorHex INTEGER DEFAULT 0,"
        "textColorHex INTEGER DEFAULT 0,"
        "`order` INTEGER DEFAULT 0)");

    await rootBundle
        .loadString("assets/data/initRecordTypeDefaultData.json")
        .then((jsonStr) async {
      List jsonList = jsonDecode(jsonStr);
      for (var element in jsonList) {
        Map<String, dynamic> map = RecordType.fromJson(element).toJson();
        map.remove("id");
        await db.insert('record_types', map);
      }
    });
  }

  void _onUpgrade(Database db, int oldVersion, int newVersion) {
    print("数据库需要升级！旧版：$oldVersion,新版：$newVersion");
  }

  /// 关闭
  Future close() async {
    return db.close();
  }
}

extension DbHelperDaoExtension on DbHelper {
  AccountBookDao get accountBookDao => AccountBookDao(db: db);
  AccountRecordDao get accountRecordDao => AccountRecordDao(db: db);
  PayMethodDao get payMethodDao => PayMethodDao(db: db);
  RecordTypeDao get recordTypeDao => RecordTypeDao(db: db);
}

class DbDao<T extends DbModel> {
  final Database db;
  String get tableName => '';
  DbDao({required this.db});
  Future<int> insert(T model) async {
    return await db.insert(tableName, model.toJson());
  }
}

abstract class DbModel {
  DbModel.fromJson(Map data);
  Map<String, dynamic> toJson();
}
